using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Awaiter;
using Nsb.Classes;
using jQueryApi;

namespace Yoshi.Classes
{
    public delegate void PopMenuEventHandler(jQueryEvent e, string item);

    [IgnoreNamespace]
    public class PopMenu : Actor
    {
        private readonly jQueryObject _focuser;
        protected jQueryObject ClickItem;
        protected readonly jQueryObject List;
        private bool _closing;
        private Dictionary<string, PopMenuEventHandler> _actions;
        private jQueryObject _menu;

        public PopMenu()
        {
            Element = jQuery.FromHtml("<div class='PopMenuWrapper'/>");
            List = jQuery.FromHtml("<ul class='PopMenu MenuZee AboveHider'/>").AppendTo(Element).Hide();
            _focuser = jQuery.FromHtml("<div/>")
                .AppendTo(Element)
                .Attribute("tabindex", (Formulas.RandomOf(10000) + 9999).ToString())
                .Hide()
                ;
            Unselectable(_focuser);
        }

        public PopMenu WrapAround(jQueryObject el)
        {
            string display = el.GetCSS("display") ?? "inline-block";
            if (el.Parent().Is(".PopMenuWrapper"))
                el.Parent().ReplaceWith(el);
            el.ReplaceWith(Element);
            el.PrependTo(Element);
            _closing = false;
            _menu = null;
            Element.CSS(new Dictionary("display", display, "position", "relative"));
            new Await()
                .AddDx(
                    delegate
                    {
                        el
                            .Unbind("click.PopMenu")
                            .Bind("click.PopMenu",
                                  delegate
                                  {
                                      List.CSS(new Dictionary("position", "absolute", "top", el.Position().Top + el.GetOuterHeight(), "right", -10));
                                      //List.Plugin<Jewl>().Position(new Dictionary("my", "right top", "at", "right bottom", "of", el, "collision", "fit fit"));
                                      // ReSharper disable AccessToModifiedClosure
                                      if (!_closing)
                                      // ReSharper restore AccessToModifiedClosure
                                      {
                                          List.Show();
                                          _menu = List.Clone(true, true);
                                          _menu.CSS(new Dictionary("top", List.GetOffset().Top, "left", List.GetOffset().Left, "width", List.GetWidth(), "height", List.GetHeight()));
                                          List.Hide();
                                          _menu.AppendTo("body");
                                          _menu.Show();
                                          _focuser.Show().Focus();
                                          Glass(CloseEv);
                                          BtnClick();
                                      }
                                  }
                            )
                            ;

                        _focuser
                            .CSS(new Dictionary("position", "absolute", "top", el.GetOuterHeight() + 10, "left", el.GetOuterWidth() - 10, "width", 1, "height", 1))
                            .FocusOut(CloseEv);
                    }
                )
                .Commit();

            return this;
        }

        public void CloseEv(jQueryEvent e)
        {
            _closing = true;
            new Await()
                .AddDx(
                    delegate
                    {
                        _focuser.Hide();
                        GlassOff(true);
                        if (_menu != null)
                            _menu.FadeOut(120,
                                         delegate
                                         {
                                             _menu.Remove();
                                             _closing = false;
                                         });
                        MenuHide();
                    })
                .Commit();
        }

        public PopMenu AddList(Dictionary<string, PopMenuEventHandler> actions)
        {
            if (!Script.IsValue(actions) || actions == null || actions.Count == 0)
            {
#if DEBUG
                Script.Literal("debugger");
#endif
                throw new Exception(Exceptions.ArgumentNull);
            }
            _actions = actions;
            foreach (KeyValuePair<string, PopMenuEventHandler> p in _actions)
            {
                if (jQuery.IsFunction(p.Value))
                {
                    jQueryObject item = jQuery.FromHtml("<li class='PopMenuItem' style='clear:both'/>")
                        .AppendTo(List)
                        .Data("MenuData", p.Key)
                        .Data("MenuFn", p.Value)
                        .MouseDown(
                            delegate(jQueryEvent e)
                            {
                                // Click could be on <a> or <li> hence use CurrentTarget to get <li>
                                ClickItem = jQuery.FromElement(e.CurrentTarget);
                                string nd = (string)ClickItem.GetDataValue("MenuData");
                                PopMenuEventHandler fn = (PopMenuEventHandler)ClickItem.GetDataValue("MenuFn");
                                fn(e, nd);
                                ItemClick();
                            }
                        )
                        ;
                    jQuery.FromHtml("<span/>")
                        .AppendTo(item)
                        .Html(p.Key)
                        ;
                }
                else
                {
                    if (String.IsNullOrEmpty((string)(object)p.Value))
                    {
                        jQuery.FromHtml("<div class='Inactive'/>")
                            .AppendTo(List)
                            .Html(p.Key)
                            ;
                    }
                    else
                    {
                        jQueryObject spacer = jQuery.FromHtml("<div class='Spacer' style='clear:both'/>")
                            .AppendTo(List);

                        jQuery.FromHtml("<div style='display:inline-block;width:50%;float:right'><hr></div><div style='float:left'>" + p.Value + "</div>")
                            .AppendTo(spacer);
                    }
                }
            }
            return this;
        }

        public virtual void BtnClick()
        {
        }

        public virtual void ItemClick()
        {
        }

        public virtual void MenuHide()
        {
        }
    }
}